#ifndef RoXmlStream__h
#define RoXmlStream__h


#include <QtCore>
#include <QtXml>

#include "RoStanzas.h"

class RoAbstractModule;


class RoXmlStream:
    public QObject
{
    Q_OBJECT

public:

    typedef QObject super;

    enum Flags
    {
        LogIncomingTrafic = 1,
        LogOutgoingTrafic = 2,
        LogTraffic = LogIncomingTrafic | LogOutgoingTrafic
    };

    RoXmlStream(RoAbstractModule * module, QIODevice * device, uint flags);

    QIODevice * device() const;

    RoAbstractModule * parentModule() const;

    /// @return Success.
    bool writeStanza(RoStanza stanza);

    /// Поток открыт и работает нормально
    bool isOpen();

public slots:

    /// Открыть исходящий поток
    void openStream();

    /// Закрыть исходящий поток и разорвать соединение
    void closeStream();

protected:

    RoAbstractModule * parent() const;

private:

    class DomBuilder:
        public RoStanza
    {
    public:
        void appendTokenFromStream(QXmlStreamReader * reader);
    private:
        QDomNode currentNode;
    };

    DomBuilder incomingStanza;

    QPointer<QIODevice> _device;

    QXmlStreamReader * reader;
    QXmlStreamWriter * writer;

    bool isOutgoingStreamOpened;

    /// Уровень вложенности XML-элемента во входящем потоке
    /// Изначально 0; в потоке — 1; в строфе — 2 и выше.
    int elementLevel;

    quint64 currentId;

    /// Сгенерировать идентификатор для строфы
    RoStanzaId nextId();

    void writeDomElement(QDomElement element);

    QString localModuleName();
    QString remoteModuleName();

    void (*logIncomingTrafic)(const QString & prefix, const RoStanza & stanza);
    void (*logOutgoingTrafic)(const QString & prefix, const RoStanza & stanza);

    static void logTraficToQDebug(const QString & prefix, const RoStanza & stanza);
    static void DontLog(const QString & prefix, const RoStanza & stanza);

private slots:

    void read();

signals:

    void stanza(RoStanza);

}; // class RoXmlStream


#endif // RoXmlStream__h
